using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.Publishing.WebControls;
using Microsoft.SharePoint.Publishing.Fields;

namespace SharePointing.Features.MetaTags.Controls
{
    /// A Field control that binds to fields of type LinkField and is 
    /// specialized to select and render embedded media files.
    /// The RenderFieldForDisplay function generates the HTML markup to 
    /// display the media file.  The MediaSelector control is
    /// used at edit time to allow authors to select a media file in
    /// the Asset Picker dialog box.
    public class MediaPlayerFieldControl : BaseFieldControl
    {
        private MediaSelector mediaSelector = new MediaSelector();

        public MediaPlayerFieldControl()
        {
        }

        /// Gets and sets the value in the edit controls
        public override object Value
        {
            get
            {
                LinkFieldValue mediaUrlValue = new LinkFieldValue();
                mediaUrlValue.NavigateUrl = this.mediaSelector.MediaUrl;
                mediaUrlValue.Text = LinkFieldValue.GetDefaultDisplayText(mediaUrlValue.NavigateUrl);

                return mediaUrlValue;
            }
            set
            {
                LinkFieldValue mediaLinkFieldValue = value as LinkFieldValue;
                if (null != mediaLinkFieldValue)
                {
                    this.mediaSelector.MediaUrl = mediaLinkFieldValue.NavigateUrl;
                }
                else
                {
                    this.mediaSelector.MediaUrl = String.Empty;
                }
            }
        }

        /// Get the default name used to find the template and 
        /// control for the MediaPlayerSelector in the control 
        /// template ASCX files.
        protected override string DefaultTemplateName
        {
            get { return "MediaPlayerFieldControl"; }
        }

        private const string AllowExternalUrlsViewStateKey = "AllowExternalUrls";
        /// A flag that determines whether to allow saving of external 
        /// media URLs.
        public bool AllowExternalUrls
        {
            get
            {
                // Return true by default if not already in view state.
                if (ViewState[AllowExternalUrlsViewStateKey] == null)
                {
                    return true;
                }
                return (bool)ViewState[AllowExternalUrlsViewStateKey];
            }
            set
            {
                ViewState[AllowExternalUrlsViewStateKey] = value;
            }
        }

        /// Creates the edit control when not in display mode.
        protected override void CreateChildControls()
        {

            base.CreateChildControls();

            if (this.ControlMode != SPControlMode.Display)
            {
                MediaSelector mediaSelectorInTemplate = this.TemplateContainer.FindControl(this.TemplateName) as MediaSelector;

                if (null == mediaSelectorInTemplate)
                {
                    // No media selector was found in the control
                    // template ASCX files. Add the default selector.
                    this.Controls.Add(this.mediaSelector);
                }
                else
                {
                    // Get the media selector from the control 
                    // template ASCX file.
                    mediaSelectorInTemplate.MediaUrl = this.mediaSelector.MediaUrl;
                    this.mediaSelector = mediaSelectorInTemplate;
                }
            }
        }

        /// Gets the current value for the media URL as stored
        /// in the list item.
        private string itemFieldValueMediaUrl
        {
            get
            {
                LinkFieldValue currentLinkValue = this.ItemFieldValue as LinkFieldValue;
                if (null != currentLinkValue)
                {
                    return currentLinkValue.NavigateUrl;
                }
                else
                {
                    return String.Empty;
                }
            }
        }

        /// Renders the current list item value for the media URL
        /// with embedded media player markup.
        /// <param name="output"></param>
        protected override void RenderFieldForDisplay(System.Web.UI.HtmlTextWriter output)
        {
            if (!String.IsNullOrEmpty(this.itemFieldValueMediaUrl))
            {
                output.Write(MediaRenderingUtilities.GetMediaPlayerHtmlMarkup(this.itemFieldValueMediaUrl));
            }
        }

        /// Verifies that the MediaUrl is valid.
        public override void Validate()
        {
            base.Validate();
            if (this.IsValid)
            {
                LinkFieldValue currentMediaUrlValue = this.Value as LinkFieldValue;

                if (currentMediaUrlValue == null || String.IsNullOrEmpty(currentMediaUrlValue.NavigateUrl))
                {
                    // Ensure the field is not required.
                    if (this.Field != null && this.Field.Required)
                    {
                        this.IsValid = false;
                        this.ErrorMessage = "This field is required and must contain a media file URL.";
                        return;
                    }
                    else
                    {
                        // The field is empty and not required.
                        // The data is valid.
                        return;
                    }
                }

                // Perform validation on the media file URL.
                HtmlValidationContext validationContext = new HtmlValidationContext();

                if (!this.AllowExternalUrls)
                {
                    // Restrict URLs to be either from the current site
                    // collection or server-relative.
                    validationContext.RestrictUrlsToSiteCollection = true;
                    validationContext.GuidOfThisSiteCollection = SPContext.Current.Site.ID;
                }

                bool droppedTags;
                bool droppedUrls;
                LinkFieldValue validatedValue = validationContext.ValidateLinkValue(currentMediaUrlValue,out droppedTags,out droppedUrls);

                if (droppedUrls || String.IsNullOrEmpty(validatedValue.NavigateUrl))
                {
                    // The media file URL in the link field value was
                    // not valid so report the error message.
                    // Setting IsValid to false stops saving the page.
                    this.IsValid = false;
                    this.ErrorMessage = "The URL for the media file was invalid.";
                    if (!this.AllowExternalUrls)
                    {
                        this.ErrorMessage += "  You must select a URL within the current site collection.";
                    }
                }
            }
        }
    }

    /// This edit control for the MediaPlayerFieldControl has 
    /// a toolbar and text box for selecting a media file URL.
    /// This example intentionally uses a separate toolbar button
    /// and text box for the AssetUrlSelctor to show a more complex
    /// example. You can use an AssetUrlSelector control instead of 
    /// a TextBox child control, which displays its own browse button.
    public class MediaSelector : WebControl
    {
        private TextBox mediaUrlTextBox = new TextBox();

        public MediaSelector()
        {
        }

        /// This is the media URL value that you can edit in the text
        /// box or Asset Picker dialog box.
        public string MediaUrl
        {
            get { return this.mediaUrlTextBox.Text; }
            set { this.mediaUrlTextBox.Text = value; }
        }

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);

            // This ensures that the TextBox child control receives
            // its postback.
            EnsureChildControls();
        }

        /// Gets JavaScript required to launch an Asset Picker dialog
        /// box for choosing a media file URL.
        private string GetAssetPickerButtonScript()
        {
            AssetUrlSelector mediaAssetSelector = new AssetUrlSelector();

            // When the AssetUrlSelector control is not added to the
            // page control tree, the Page and ID properties are
            // required because
            // AssetUrlSelector.GetClientLaunchPickerReference() 
            // needs register script in the page.
            mediaAssetSelector.Page = this.Page;
            mediaAssetSelector.ID = "MediaUrlAssetSelector";

            // Uses the TextBox client ID to connect the Asset Picker
            // dialog box to the text box.
            mediaAssetSelector.AssetUrlClientID = this.mediaUrlTextBox.ClientID;

            // Autopostback to see the new media file rendered after
            // clicking OK on the Asset Picker dialog box.
            mediaAssetSelector.AutoPostBack = true;

            mediaAssetSelector.OverrideDialogTitle = "Select a media file";
            mediaAssetSelector.OverrideDialogDescription = "Select a media file to embed in this page";
            mediaAssetSelector.UseImageAssetPicker = false;

            return mediaAssetSelector.GetClientLaunchPickerReference();
        }

        private Literal mediaPlayerOutput = new Literal();
        protected override void CreateChildControls()
        {
            SimpleToolbar mediaSelectorToolbar = new SimpleToolbar();
            mediaSelectorToolbar.ID = "ToolBar";

            this.Controls.Add(mediaSelectorToolbar);

            Label mediaUrlLabel = new Label();
            mediaUrlLabel.Text = "Selected media file URL: ";
            mediaUrlLabel.AssociatedControlID = "MediaUrlTextBox";
            this.Controls.Add(mediaUrlLabel);

            this.mediaUrlTextBox.ID = "MediaUrlTextBox";
            this.mediaUrlTextBox.CssClass =
              "ms-input ms-lactiontable sample-mediaselector-urltextbox";
            this.Controls.Add(this.mediaUrlTextBox);

            // Add the button after the rest so that the text box
            // ClientID is already determined and can be connected
            // in the Asset Picker dialog box client script.
            mediaSelectorToolbar.AddToolbarButton(
                "SelectMediaFile",
                "Select a media file",
                this.GetAssetPickerButtonScript(),
                "Open a picker to select a media file URL");

            // Add a refresh button to perform a basic postback to
            // to update the MediaUrl rendering.
            mediaSelectorToolbar.AddToolbarButton(
                "RefreshMediaFile",
                "Refresh",
                this.Page.ClientScript.GetPostBackEventReference(this,
                  String.Empty),
                  "Refresh the page to reload the current media file URL",
                  "/_layouts/IMAGES/refresh.gif");

            // If there is a media file URL, this code creates
            // the media player markup.
            this.Controls.Add(this.mediaPlayerOutput);
        }

        protected override void OnPreRender(EventArgs e)
        {
            string mediaFileOutputHtml =
              MediaRenderingUtilities.GetMediaPlayerHtmlMarkup(this.MediaUrl);
            if (String.IsNullOrEmpty(mediaFileOutputHtml))
            {
                this.mediaPlayerOutput.Text =
                  "<BR>{There is no valid media file URL to display}<BR>";
            }
            else
            {
                this.mediaPlayerOutput.Text =
                  "<BR>" + mediaFileOutputHtml + "<BR>";
            }

            base.OnPreRender(e);
        }
    }

    public static class MediaRenderingUtilities
    {
        /// Take a media file URL and generate HTML markup
        /// for playing the file.
        /// <param name="mediaUrl"></param>
        public static string GetMediaPlayerHtmlMarkup(string mediaUrl)
        {
            // HtmlUrlAttributeEncode returns an empty string if the 
            // URL protocol is not allowed (e.g., JavaScript:)
            string encodedUrl = SPHttpUtility.HtmlUrlAttributeEncode(mediaUrl);

            if (String.IsNullOrEmpty(encodedUrl))
            {
                return String.Empty;
            }
            else
            {
                return String.Format(MediaPlayerHtmlMarkupFormat, encodedUrl);
            }
        }

        // Currently, this code includes only a parameter for the media
        // file URL, but it could also include parameters for the
        // width, height, and other rendering properties from field
        // control properties or authored data value properties.
        private const string MediaPlayerHtmlMarkupFormat = @"
            <object type=""video/x-ms-wmv""
              data=""{0}""
              width=""300"" height=""450"">
              <param name=""src"" value=""{0}"" />
              <param name=""autostart"" value=""true"" />
              <param name=""controller"" value=""true"" />
            </object>
            ";
    }
}